package com.pvdnc.riru.appinjector;

import android.app.Application;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;

import java.lang.reflect.Method;
import java.util.List;

import static android.content.Context.CONTEXT_IGNORE_SECURITY;
import static android.content.Context.CONTEXT_INCLUDE_CODE;

public class AppModuleLoader {
    private static final String TAG= AppModuleLoader.class.getSimpleName();

    public static final AppModuleLoader INSTANCE=new AppModuleLoader();

    public static final String MODULE_META_DATA_NAME="riru_hook_module";
    public static final String MODULE_TARGET_META_DATA_NAME="riru_target_app";

    public void loadModules(Application callingApp){
        PackageManager pm=callingApp.getPackageManager();
        List<PackageInfo> pkgInfoList= pm.getInstalledPackages(PackageManager.GET_META_DATA);
        for (PackageInfo pkgInfo:pkgInfoList){
            loadModule(callingApp,pkgInfo);
        }
        //移除Hook环境
        AppClassLoader.INSTANCE.removeRiruClasses();
        Log.d(TAG,"recovered app classloader:\n\t"+callingApp.getClassLoader());
    }

    private void loadModule(Application callingApp,PackageInfo pkgInfo){
        String callingPkgName=callingApp.getPackageName();

        String pkgName=pkgInfo.packageName;
        Bundle bundle= pkgInfo.applicationInfo.metaData;
        if(bundle==null)//如果pkg没有meta-data标签，那么就是null
            return;
        String entry= bundle.getString(MODULE_META_DATA_NAME, null);
        if(entry==null)
            return;
        String targetApp=bundle.getString(MODULE_TARGET_META_DATA_NAME,null);
        if(targetApp!=null){//不带这个标签默认认为是作用于所有app
            if(!callingPkgName.equals(targetApp))//不是目标app
                return;
        }
        try {
            Log.d(TAG, "pkg:" + pkgName + " is a riru hook module");

            Context moduleContext= callingApp.createPackageContext(pkgName,
                    CONTEXT_INCLUDE_CODE | CONTEXT_IGNORE_SECURITY);
            Class<?> entryClass= moduleContext.getClassLoader().loadClass(entry);
            Log.d(TAG,"module entry:"+entryClass);
            Method onLoadMethod= entryClass.getDeclaredMethod("onLoad",Application.class);
            onLoadMethod.setAccessible(true);
            onLoadMethod.invoke(null,callingApp);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
